package com.demo.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.demo.wrapper.RequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;

@Slf4j
public class SignUtil {
	
	/**
	 * 签名
	 * @param body	参数
	 * @param signKey	签名密钥
	 * @return
	 */
	public static String sign(JSONObject body, String signKey){
		
		//对参数进行ASCII码从小到大排序（字典序）
		List<Entry<String, Object>> akeys = new ArrayList<Entry<String,Object>>(body.entrySet());
		Collections.sort(akeys,new Comparator<Entry<String, Object>>() {
			@Override
			public int compare(Entry<String, Object> o1, Entry<String, Object> o2) {
				return o1.getKey().compareTo(o2.getKey());
			}
		});

		StringBuffer sb = new StringBuffer();
		sb.append(signKey + ":");
		for(Entry<String, Object> item : akeys){
			String key = item.getKey();
			Object val = item.getValue();

			if(null != val && !"".equals(val.toString())
					&& !"sign".equals(key)) {
				sb.append(key + ":" + val.toString() + ":");
			}
		}

		sb.append(signKey);
		log.info("拼接字符串：{}",sb.toString());
		String sign = DigestUtils.md5Hex(sb.toString()).toUpperCase();
		return sign;
	}

	/**
	 * 验证签名（application/json方式提交）
	 * @param request
	 * @param signKey
	 * @return
	 */
	public static boolean checkSignJson(HttpServletRequest request, String signKey) throws IOException {
		JSONObject params = getReqBodyParams(request);
		log.info("接口参数：{}",params);
		return checkSign(params,signKey);
	}

	/**
	 * 验证签名（application/x-www-form-urlencoded方式提交）
	 * @param request
	 * @param signKey
	 * @return
	 */
	public static boolean checkSignForm(HttpServletRequest request, String signKey) throws IOException {
		Map<String, Object> params = getReqParams(request);
		log.info("接口参数：{}",params);
		return checkSign(params,signKey);
	}

	/**
	 * 验证签名
	 * @param params
	 * @return
	 */
	public static boolean checkSign(Map<String, Object> params,String signKey){

		DateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		DateFormat sdf2 = new SimpleDateFormat("yyyyMMddHHmm");

		try {
			if(params.get("sign") != null) {
				String sign = params.get("sign").toString();
				String time = params.get("time").toString();
				JSONObject body = JSON.parseObject(params.get("body").toString());
				String signTime = sdf2.format(sdf1.parse(time));
				body.put("signTime", signTime);

				String _sign = sign(body,signKey);
				if(_sign.equals(sign)){
					return true;
				}

				log.error("签名错误：客户签名【" + sign + "】，生成签名：【" + _sign + "】");
			}

		} catch (Exception e) {
			log.error("Exception", e);
		}

		return false;
	}

	/**
	 * 获取请求参数（请求体方式）
	 * @param request
	 * @return
	 * @throws IOException
	 */
	public static JSONObject getReqBodyParams(HttpServletRequest request) throws IOException {
		RequestWrapper myRequestWrapper = new RequestWrapper(request);
		String body = myRequestWrapper.getBody();
		return JSON.parseObject(body);
	}

	/**
	 * 获取请求参数(form表单方式)
	 * @param request
	 * @return
	 */
	private static Map<String,Object> getReqParams(HttpServletRequest request){

		Map properties = request.getParameterMap();
		Map<String,Object> returnMap = new HashMap<>();
		Iterator entries = properties.entrySet().iterator();
		Entry entry;
		String name = "";
		String value = "";
		while (entries.hasNext()) {
			entry = (Entry) entries.next();
			name = (String) entry.getKey(); 
			
			Object valueObj = entry.getValue(); 
			if(null == valueObj){ 
				value = ""; 
			}
			else if(valueObj instanceof String[]){ 
				String[] values = (String[])valueObj;
				for(int i=0;i<values.length;i++){ 
					 value = values[i] + ",";
				}
				value = value.substring(0, value.length()-1); 
			}
			else{
				value = valueObj.toString(); 
			}
			
			returnMap.put(name, value);
		}
		
		return returnMap;
	}
}
